using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

public enum RestAPIProtocol
{
    
};

public enum STATUS
{
    Success,
    Fail,
};

public delegate void RestAPIReturnCallback(Hashtable returnData);

public class RestAPI : MonoBehaviour
{
    static RestAPI _singleton;

    public static RestAPI singleton
    {
        get { return _singleton; }
        set { _singleton = value; }
    }

    private bool _isDebugMode = false;
    public bool debugMode
    {
        get { return _isDebugMode; }
        set { _isDebugMode = value; }
    }

    private object thisLock = new object();
    private int sequenceNumber = 0;

    private string target
    {
        get
        {
//            if (CSceneManager.BuildType == 1)
//                return "211.189.163.179/dice_deploy/api"; //QA
//            else if (CSceneManager.BuildType == 0)
//                return "211.189.163.178/dice_deploy/api"; //DEV
//            else if (CSceneManager.BuildType == 2)
//                return PlayerPrefs.GetString("CustomGameServerAddress") + "/dice_deploy/api";
//            else
                return "211.189.163.178/dice_deploy/api"; //DEV
        }
    }

    private System.TimeSpan span = new System.TimeSpan(0, 0, 0, 45, 0);

    // Use this for initialization
    void Awake()
    {
        Debug.LogError(target);
        DontDestroyOnLoad(gameObject);
        if (RestAPI.singleton == null)
            RestAPI.singleton = this;
    }


    public int CreateUser(RestAPIReturnCallback callback, string name, int pawnIndex)
    {
        int sequenceNumber;
        lock (thisLock)
        {
            sequenceNumber = ++this.sequenceNumber;
        }

        if (!_isDebugMode)
        {
            Hashtable sendData = new Hashtable();
            Hashtable header = new Hashtable();

            sendData.Add("DeviceId", SystemInfo.deviceUniqueIdentifier);
            sendData.Add("Name", name);
            sendData.Add("Pawn", pawnIndex);

            //StringBuilder builder = new StringBuilder();

//            StartCoroutine(CallRestAPIByHTTP(callback, LC_WWW.HTTPMETHOD.POST, sequenceNumber, target + "/user2", RestAPIProtocol.CREATEUSER, sendData, header));
        }
        else
        {

        }

        return sequenceNumber;
    }

    public int GetServerUnixTime(RestAPIReturnCallback callback)
    {
        int sequenceNumber;
        lock (thisLock)
        {
            sequenceNumber = ++this.sequenceNumber;
        }

        if (!_isDebugMode)
        {
            Hashtable sendData = new Hashtable();
            Hashtable header = new Hashtable();

            //			StringBuilder builder = new StringBuilder();
            //			builder.Append("?pid="+LCSocialPlatform.myUserInfo.userId);

//            StartCoroutine(CallRestAPIByHTTP(callback, LC_WWW.HTTPMETHOD.GET, sequenceNumber, target + "/user", RestAPIProtocol.GETSERVERUNIXTIME, sendData, header));
        }
        else
        {

        }

        return sequenceNumber;
	}

    private LC_WWW lc_www = null;
    private IEnumerator CallRestAPIByHTTP(RestAPIReturnCallback callback, LC_WWW.HTTPMETHOD method, int sequenceNumber, string url, RestAPIProtocol bodProtocol, Hashtable parameters, Hashtable header)
    {
        lc_www = new LC_WWW(url);

        lc_www.Method = method;
        lc_www.Parameters = parameters;
//        Authenticator auth = new Authenticator();
        //		header.Add("di", "A4CF2290-4C94-4CB8-8F37-DA96C72705B8");
        //		header.Add("di", "fc01d789841ed7842875f64988cf2e9bd6882cd3");
        //		header.Add("di", "A4CF2290-4C94-4CB8-8F37-DA96C72705B8");
        //		header.Add("di", "7e91ec19b53511d60732c0f0e0078c34724aa473");
//        header.Add("ui", MyInfo.Instance.DBID);
//        header.Add("di", SystemInfo.deviceUniqueIdentifier);
//        header.Add("Au", auth.GetCode(null, SystemInfo.deviceUniqueIdentifier));
        //		header.Add("Au", auth.GetCode(null, "fc01d789841ed7842875f64988cf2e9bd6882cd3"));
        //		header.Add("Au", auth.GetCode(null, "A4CF2290-4C94-4CB8-8F37-DA96C72705B8"));
        //		header.Add("Au", auth.GetCode(null, "7e91ec19b53511d60732c0f0e0078c34724aa473"));
        //		header.Add("Au", "723458");

        lc_www.RequestHeaders = header;

        yield return StartCoroutine(GetRestApiReturnData(callback, sequenceNumber, lc_www, bodProtocol));
    }

    private IEnumerator GetRestApiReturnData(RestAPIReturnCallback callback, int sequenceNumber, LC_WWW lc_www, RestAPIProtocol bodProtocol)
    {
        yield return null;
        Hashtable returnData = new Hashtable();
        returnData.Add("protocol", bodProtocol);
        Debug.Log(Application.internetReachability);
        switch (Application.internetReachability)
        {
            case NetworkReachability.ReachableViaCarrierDataNetwork:
            case NetworkReachability.ReachableViaLocalAreaNetwork:
                lc_www.Send();

                System.DateTime time = System.DateTime.UtcNow;

                bool timeOver = false;

                while (!lc_www.IsDone)
                {
                    yield return null;

                    if ((System.DateTime.UtcNow - time) > span)
                    {
                        timeOver = true;
                        break;
                    }
                }


                if (timeOver)
                {
                    returnData.Add("error", "TimeOver");
                    returnData.Add("status", lc_www.Status.ToString());
                    Debug.LogError(lc_www.error);
                }
                else if (lc_www.Status >= 200 && lc_www.Status <= 299)
                {
                    if (!string.IsNullOrEmpty(lc_www.text))
                        returnData = ParsingServerData(lc_www.text, bodProtocol);
                }
                else if (lc_www.Status > 300 && lc_www.Status < 500)
                {
                    
                }
                else if (lc_www.Status == 500)
                {
                    returnData.Add("error", "Internal Server Error");
                }
                break;
        }

        if (!returnData.ContainsKey("error"))
        {
            if (callback.Target != null)
                callback(returnData);
        }
        //        else
        //        {
        //            Debug.LogError("Rest Error! - " + returnData["error"].ToString());
        //        }
    }


    private IEnumerator GetRestApiReturnData(RestAPIReturnCallback callback, int sequenceNumber, string url, LC_WWW.HTTPMETHOD method, WWWForm form, RestAPIProtocol bodProtocol)
    {
        yield return null;
        Hashtable returnData = new Hashtable();
        returnData.Add("protocol", bodProtocol);
        NetworkReachability networkStatus = NetworkReachability.NotReachable;
        if (Application.platform == RuntimePlatform.Android)
        {
            //			int status = LCPlatform.AndroidCheckNetworkStatus();
            //			if( status == 0 )
            //				networkStatus = NetworkReachability.NotReachable;
            //			else if( status == 1 )
            //				networkStatus = NetworkReachability.ReachableViaLocalAreaNetwork;
            //			else if( status == 2 )
            //				networkStatus = NetworkReachability.ReachableViaCarrierDataNetwork;
        }
        else
        {
            networkStatus = Application.internetReachability;
        }

        switch (networkStatus)
        {
            case NetworkReachability.ReachableViaCarrierDataNetwork:
            case NetworkReachability.ReachableViaLocalAreaNetwork:
#if UNITY_IPHONE
			url = System.Uri.EscapeUriString(url);
#endif
                WWW lc_www;
                if (method == LC_WWW.HTTPMETHOD.GET)
                    lc_www = new WWW(url);
                else
                    lc_www = new WWW(url, form);

                System.DateTime time = System.DateTime.UtcNow;

                bool timeOver = false;

                while (!lc_www.isDone)
                {
                    yield return null;

                    if ((System.DateTime.UtcNow - time) > span)
                    {
                        timeOver = true;
                        break;
                    }
                }

                if (timeOver)
                {
                    returnData.Add("error", "TimeOver");
                }
                else if (lc_www.error == null)
                {
                    //				Debug.Log("no error");
                    Debug.Log("Server Says : " + lc_www.text);
                    returnData = ParsingServerData(lc_www.text, bodProtocol);
                }
                else if (lc_www.error != null)
                {
                    Debug.Log("Error! : " + lc_www.error + "\n" + lc_www.url);

                    if (lc_www.responseHeaders.ContainsKey("STATUS"))
                        Debug.Log("Error! : " + lc_www.responseHeaders["STATUS"].ToString());
                    returnData.Add("error", lc_www.error.ToString());
                }
                break;
            default:
                break;
        }


        if (!returnData.ContainsKey("error"))
        {
            callback(returnData);
        }
        else
        {
            Debug.LogError("Rest Error! - " + returnData["error"].ToString());
        }
    }

    private Hashtable ParsingServerData(string returnString, RestAPIProtocol bodProtocol)
    {
        Hashtable returnData = new Hashtable();

        if (returnString.Contains("{") || returnString.Contains("["))
        {
            //glog.debug("RETURN STR -- " + returnString);
            //          JsonData data = JsonMapper.ToObject(returnString);

            ArrayList jsonArray = new ArrayList();
            Hashtable jsonTable = new Hashtable();

            if (returnString.IndexOf("[") == 0)
                jsonArray = JSON.JsonDecode(returnString) as ArrayList;
            else
                jsonTable = JSON.JsonDecode(returnString) as Hashtable;

            //for (int i = 0; i < data.Count; i++)
            //{
            //    glog.debug("JSON Data [" + i + "] -- " + data);
            //    glog.debug("JSON Type [" + i + "] -- " + data.GetJsonType());
            //}

            switch (bodProtocol)
            {
                default:
                    break;
            }
        }
        else
        {
            returnData.Add("json", "Datatype is not json");
        }

        returnData.Add("protocol", bodProtocol);

        return returnData;
    }

    #region Static Function
    public static DateTime ConvertFromUnixTimestamp(double timestamp)
    {
        DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Unspecified);
        return origin.AddSeconds(timestamp);
    }

    public static double ConvertToUnixTimestamp(DateTime date)
    {
        DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0);
        return (date - origin).TotalSeconds;
    }
    string UTF8Encoiding(string target)
    {
        byte[] utf8Bytes = Encoding.UTF8.GetBytes(target);
        return Encoding.UTF8.GetString(utf8Bytes);
    }
    #endregion
}